﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection.Emit;
using System.Data.Common;
using System.Data;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;

namespace OrmAuto
{
		public class DynamicBuilder
		{
				private delegate object Load(DbDataReader dataReader);
				private Load handler;

				//private DynamicBuilder() { }



    // prelevo le istanze
				public object Build(DbDataReader reader)
				{
						return handler(reader);
				}


				//public static DynamicBuilder CreateBuilder(IDataRecord reader,object T)
				//{
				//  DynamicBuilder<T> result = new DynamicBuilder<T>();
				//  DynamicMethod method = new DynamicMethod("DynamicCreate",
				//      typeof(T), new Type[] { typeof(DbDataReader) },T.GetType()  , true);

				//  ILGenerator generator = method.GetILGenerator();
				//  generator.DeclareLocal(T.GetType());

				//  generator.Emit(OpCodes.Newobj, T.GetType().GetConstructor(Type.EmptyTypes));
				//  generator.Emit(OpCodes.Stloc_0);

				//  MethodInfo getValue = reader.GetType().GetMethod("get_Item", new Type[] { typeof(int) });

				//  for (int i = 0; i < reader.FieldCount; i++)
				//  {
				//    PropertyInfo propertyInfo = T.GetType().GetProperty(reader.GetName(i));
				//    if (propertyInfo != null && propertyInfo.GetSetMethod() != null)
				//    {
				//      generator.Emit(OpCodes.Ldloc_0);
				//      generator.Emit(OpCodes.Ldarg_0);
				//      generator.Emit(OpCodes.Ldc_I4, i);
				//      generator.Emit(OpCodes.Callvirt, getValue);
				//      generator.Emit(OpCodes.Unbox_Any, reader.GetFieldType(i));
				//      generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());
				//    }
				//  }

				//  generator.Emit(OpCodes.Ldloc_0);
				//  generator.Emit(OpCodes.Ret);
				//  result.handler = (Load)method.CreateDelegate(typeof(Load));
				//  return result;
				//}//fm

				public static DynamicBuilder CreateBuilderSafeNull(IDataRecord reader,object T	 )
				{
						DynamicBuilder result = new DynamicBuilder();
						DynamicMethod method = new DynamicMethod("DynamicCreate",
										T.GetType(), new Type[] { typeof(DbDataReader) }, T.GetType(), true);

						ILGenerator generator = method.GetILGenerator();
						generator.DeclareLocal(T.GetType());

						generator.Emit(OpCodes.Newobj, T.GetType().GetConstructor(Type.EmptyTypes));
						generator.Emit(OpCodes.Stloc_0);

						MethodInfo getValue = reader.GetType().GetMethod("get_Item", new Type[] { typeof(int) });
						MethodInfo metIsDbNull = reader.GetType().GetMethod("IsDBNull", new Type[] { typeof(int) });
						FieldInfo nullType = typeof(DBNull).GetField("Value");
						MethodInfo mebox = typeof(System.Windows.Forms.MessageBox).GetMethod("Show", new Type[] { typeof(string) });
						MethodInfo toStr = typeof(Object).GetMethod("ToString");

						for (int i = 0; i < reader.FieldCount; i++)
						{
								PropertyInfo propertyInfo = T.GetType().GetProperty(reader.GetName(i));
								if (propertyInfo != null && propertyInfo.GetSetMethod() != null)
								{
										System.Reflection.Emit.Label OmitirNullos = generator.DefineLabel();
										generator.Emit(OpCodes.Ldarg_0);
										generator.Emit(OpCodes.Ldc_I4, i);
										generator.Emit(OpCodes.Callvirt, metIsDbNull);
										generator.Emit(OpCodes.Brtrue, OmitirNullos);

										generator.Emit(OpCodes.Ldloc_0);
										generator.Emit(OpCodes.Ldarg_0);
										generator.Emit(OpCodes.Ldc_I4, i);
										generator.Emit(OpCodes.Callvirt, getValue);
										generator.Emit(OpCodes.Unbox_Any, reader.GetFieldType(i));
										generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());
										generator.MarkLabel(OmitirNullos);
								}
						}

						generator.Emit(OpCodes.Ldloc_0);
						generator.Emit(OpCodes.Ret);
						result.handler = (Load)method.CreateDelegate(typeof(Load));
						return result;
				}//fm

				//public static DynamicBuilder<T> CreateBuilderAttributi(IDataRecord reader)
				//{
				//  DynamicBuilder<T> result = new DynamicBuilder<T>();
				//  DynamicMethod method = new DynamicMethod("DynamicCreate",
				//      typeof(T), new Type[] { typeof(DbDataReader) }, typeof(T), true);

				//  ILGenerator generator = method.GetILGenerator();
				//  generator.DeclareLocal(typeof(T));

				//  generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
				//  generator.Emit(OpCodes.Stloc_0);

				//  MethodInfo getValue = reader.GetType().GetMethod("get_Item", new Type[] { typeof(int) });

				//  for (int i = 0; i < reader.FieldCount; i++)
				//  {
				//    PropertyInfo propertyInfo = typeof(T).GetProperty(reader.GetName(i));

				//    if (propertyInfo.GetCustomAttributes(typeof(DS_attrColMappingAttribute), false).Length
				//        > 0)
				//    {
				//      if (propertyInfo != null && propertyInfo.GetSetMethod() != null)
				//      {
				//        generator.Emit(OpCodes.Ldloc_0);
				//        generator.Emit(OpCodes.Ldarg_0);
				//        generator.Emit(OpCodes.Ldc_I4, i);
				//        generator.Emit(OpCodes.Callvirt, getValue);
				//        generator.Emit(OpCodes.Unbox_Any, reader.GetFieldType(i));
				//        generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());

				//      }
				//    }
				//  }

				//  generator.Emit(OpCodes.Ldloc_0);
				//  generator.Emit(OpCodes.Ret);
				//  result.handler = (Load)method.CreateDelegate(typeof(Load));
				//  return result;
				//}//fm



		}//fc


}
